package cn.yqn.basic.service.impl;

import cn.yqn.basic.constants.BaseConstants;
import cn.yqn.basic.exception.BusinessException;
import cn.yqn.basic.service.IVerifyCodeService;
import cn.yqn.basic.utils.StrUtils;
import cn.yqn.basic.utils.VerifyCodeUtils;
import cn.yqn.user.domain.User;
import cn.yqn.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    // 图形验证码
    @Override
    public String getVerifyCode(String key) {
        // 判断前端图片验证码是否为相同
        if(StringUtils.isEmpty(key)){
            throw new BusinessException("参数有误！");
        }
        // 使用StrUtils工具生成四位数字节码
        String randomString = StrUtils.getComplexRandomString(4);
        // 放入redis中设置三分种有效
        redisTemplate.opsForValue().set(key, randomString,3, TimeUnit.MINUTES);
        // 转换为base64字节码
        return VerifyCodeUtils.VerifyCode(100, 40, randomString);
    }

    // 短信注册
    @Override
    public void smsCode(Map<String, String> map) {
        // 1.获取手机号,图形验证码,图形redisKey
        String phone = map.get("phone");
        String imageCode = map.get("imageCode");
        String imageCodeKey = map.get("imageCodeKey");
        // 2.效验前端参数不能为空
        if (StringUtils.isEmpty(phone) ||
            StringUtils.isEmpty(imageCode) ||
            StringUtils.isEmpty(imageCodeKey)
        ) {
            throw new BusinessException("参数不能为空!");
        }
        // 3.图形验证码效验
        Object obj = redisTemplate.opsForValue().get(imageCodeKey);
        if (obj == null) { // 判断为空则为过期
            throw new BusinessException("图形验证码过期,请从新验证");
        }
        // 验证码不区分大小写
        if (!obj.toString().equalsIgnoreCase(imageCode)) {
            throw new BusinessException("验证信息有误,请确认重试");
        }
        // 4.验证电话是否被注册
        User user = userMapper.findByPhone(phone);
        if (user != null) {
            throw new BusinessException("手机号已经被注册!");
        }
        // 5.判断短信是否第一次发送,短息信息是否过期
        Object value = redisTemplate.opsForValue().get(phone + BaseConstants.VerifyCodeConstant.BUSINESS_REGISTER_KEY);
        String code = null;
        // 判断第一次发送信息是否获取,没有直接生成一个保存到redis中
        if (value == null) {
            code = StrUtils.getComplexRandomString(6);
        } else {
            // 有信息则判断获取冷却一分钟是否到时,获取时间戳
            String redisTime = value.toString().split(":")[1];
            Long ltime= Long.valueOf(redisTime);
            if (System.currentTimeMillis()-ltime<60 * 1000 * 1) {
                throw new BusinessException("请勿频繁获取验证信息");
                } else {
                // 通过判断,刷新冷却时间
                code = value.toString().split(":")[0];
            }
        }
        // 将code添加到redis中发送短息提交用户
        redisTemplate.opsForValue().set(phone + BaseConstants.VerifyCodeConstant.BUSINESS_LOGIN_KEY,
        code + ":" + System.currentTimeMillis(), 3, TimeUnit.MINUTES);
        // 短息发送格式
        // SmsSendUtil.smsSend(phone,"您的验证码为："+code+",请在三分钟之内使用");
        System.out.println("您的验证码为："+code+",请在三分钟之内使用");

    }

    // 
    @Override
    public void binderSmsCode(Map<String, String> map) {
        String phone = map.get("phone");  // 手机号

        // 1. 校验，参数不能为空
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不能为空");
        }

        /**
         * key: 手机号+业务键   业务键：最好是常量
         * value: code:时间戳
         */
        // 4. 判断是否是第一次发送请求，或者是验证码过期  从redis中取
        Object value = redisTemplate.opsForValue().get(phone + BaseConstants.VerifyCodeConstant.WXBINDER);

        String code = null;
        // 4.1. 如果取不到，没有发送过，获取过期了， 直接生成一个新的验证码保存到redis
        if(value==null){ // 没取到
            code = StrUtils.getComplexRandomString(6);
        }else{
            // 4.2. 如果取到了。判断是否超过一分钟。
            String redisTime = value.toString().split(":")[1];
            long ltime = Long.valueOf(redisTime);
            // 4.2.1： 如果没超过1分钟，直接提示用户，1分钟之内不能多次发送。
            if(System.currentTimeMillis()-ltime<1*60*1000){
                throw new BusinessException("一分钟只能不能发送多次！");

            }else{
                // 4.2.2： 如果超过了一分钟，刷新过期时间，
                code = value.toString().split(":")[0];
            }
        }

        // 4.2.2： 把code存入redisz中
        redisTemplate.opsForValue().set(
                phone+BaseConstants.VerifyCodeConstant.WXBINDER,
                code+":"+System.currentTimeMillis(),
                3,
                TimeUnit.MINUTES);

        // 5. 发送短信给用户
        // SmsSendUtil.smsSend(phone,"您的验证码为："+code+",请在三分钟之内使用");
        System.out.println("您的验证码为："+code+",请在三分钟之内使用");
    }

}
